"""
    Controller for creation and printing daily payment registers.
"""

import operator
from decimal import Decimal
from turbogears import expose, redirect, identity, widgets, validate, validators, error_handler
from mnemoply import model
from mnemoply.controllers import Report
from mnemoply.controllers.lookup import LookupController, TableCol, TableLookupDataSource
from mnemoply.controllers.containers import ModelObjectContainer
from mnemoply.widgets import DictionaryField
from mnemoply.utils import LocalMenu, LocalMenuItem, objs2ids
from mnemoply.mass_actions import MassAction

class MAPrint(MassAction):
    target_class = model.DailyPaymentRegister
    name = "print"
    title = _("Print")
    read_only = True

    def call(self, objs):
        return Report.generate("DailyPayment", ids=objs2ids(objs))

class DailyPaymentRegisterController(LookupController, ModelObjectContainer, LocalMenu):
    model_object = model.DailyPaymentRegister
    lookup_columns = [
        TableCol(name='creation_date', caption=_("Date")),
        TableCol(name='org_str', caption=_("Organization")),
        TableCol(name='cash_register_str', caption=_("Cash register")),
        TableCol(name='amount', caption=_("Amount")),
    ]

    add_form = widgets.TableForm(fields=[
        widgets.CalendarDatePicker(
            label = _('Date'),
            name = '_date',
            calendar_lang = 'ru',
            format = '%d.%m.%Y',
            validator = validators.DateTimeConverter(format="%d.%m.%Y")),
        DictionaryField(
                name='organization_id',
                model_object_name='Organization',
                not_empty=True,
                label=_("Organization")),
        DictionaryField(
                name='cash_register_id',
                model_object_name='CashRegister',
                not_empty=True,
                label=_("Cash register")),
        ],
        submit_text=_("Add"),
        action='generate',
    )

    def __init__(self):
        ModelObjectContainer.__init__(self, model.DailyPaymentRegister)
        LookupController.__init__(self,
            data_source=TableLookupDataSource('daily_payment_register_lookup'),
            columns=self.lookup_columns,
            title=self.model_object.model_title,
            mass_actions_class=self.model_object,
            default_order_asc=False,
        )

        self.object_local_menu = [
            LocalMenuItem(caption=_('List'), href='../list'),
        ]

        self.local_menu.extend((
            LocalMenuItem(caption=_('Add'), href='./add'),
        ))

    @expose(template="genshi:mnemoply.templates.registers.daily_payment_add")
    def add(self):
        model_title = model.DailyPaymentRegister.model_title

        user = identity.current.user
        default_office = 0

        if user.office is not None:
            default_office = user.office.id

        cash_registers = model.CashRegister.selectBy(office=default_office)

        if cash_registers.count():
            default_cash_register = cash_registers[0]
        else:
            default_cash_register = model.CashRegister.get(0) # TODO: hack, add zero register

        return dict(add_form=self.add_form,
            model_title=model_title,
            default_cash_register=default_cash_register,
            )

    @expose()
    def recharge(self, register_id, _amount):
        register = model.DailyPaymentRegister.get(int(register_id))
        register.amount = _amount
        raise redirect("./%s/" % register_id)

    def getRecordsToReport(self, date, organization, cash_register):
        """
            Collect all payment records for this date in `cash_register` with agreements for `organization`.
        """

        pay_records = []
        for pr in model.PaymentRecord.selectBy(date=date, register=cash_register):
            if pr.studentAgreement.organization == organization:
                if pr.amount > Decimal(0):
                    pay_records.append(pr)
        return pay_records

    @identity.require(identity.has_any_permission('dba', 'DailyPaymentRegister/add'))
    @expose()
    @validate(form=add_form)
    @error_handler(add)
    def generate(self, organization_id, cash_register_id, _date):
        """
            Create new daily payment report.
        """

        organization = model.Organization.get(int(organization_id))
        cash_register = model.CashRegister.get(int(cash_register_id))

        register = model.DailyPaymentRegister.selectBy(
            creation_date=_date,
            organization=organization,
            cashRegister=cash_register)

        if len(list(register)) > 0:
            raise redirect("./%s/" % register[0].id)

        records = self.getRecordsToReport(_date, organization, cash_register)

        model.DailyPaymentRegister(
            creation_date = _date,
            organization  = organization,
            cashRegister  = cash_register,
            amount        = reduce(operator.add, [pr.amount for pr in records], Decimal(0)),
            )

        raise redirect("./")

    @expose(template="genshi:mnemoply.templates.registers.daily_payment")
    def show(self, register):
        date = register.creation_date
        cash_register = register.cashRegister
        organization = register.organization

        records = self.getRecordsToReport(date, organization, cash_register)
        # We use `reduce` for summarize all records.amount with operator `add`
        new_amount = reduce(operator.add, [pr.amount for pr in records], Decimal(0))

        return dict(
            register    = register,
            pay_records = records,
            difference  = new_amount - register.amount,
            new_amount  = new_amount,
            action      = "../recharge",
            )
    show.expose_object = True

    def fill_lookup_data_defaults(self, data):
        def get_register_name(register):
            if register:
                return register.name
            else:
                return ""

        is_parent_filled = LookupController.fill_lookup_data_defaults(self, data)
        if not is_parent_filled:
            user = identity.current.user
            default_cash_register = None

            if user.office is not None:
                default_office = user.office.id
                cash_registers = model.CashRegister.selectBy(office=default_office)
                if cash_registers.count():
                    default_cash_register = cash_registers[0]

            args = {'flt_cash_register_str': get_register_name(default_cash_register),
                    'column': ['creation_date', 'cash_register_str', 'amount']}
            data.update(args)

exposed = DailyPaymentRegisterController()